package com.example.cake.service;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.cake.entity.DTO.SysFilesDTO;
import com.example.cake.entity.SysFiles;
import com.example.cake.mapper.SysFilesMapper;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class SysFilesService extends ServiceImpl<SysFilesMapper, SysFiles> {
    @Value("${server.port}")
    private String serverPort;
    @Value("${server.ip}")
    private String serverIP;
    @Resource
    public SysFilesMapper fileMapper;
    public String upload(String basePath, MultipartFile file) throws IOException {
        String url = "";
        System.out.println("==================="+file);
        System.out.println("==================="+file.getOriginalFilename());
        String originalFilename = file.getOriginalFilename(); // 获取文件原始名字
        String contentType = FileUtil.extName(originalFilename); // 获取文件类型
        long size = file.getSize();  // 获取文件大小
        // 使用UUID生成新的文件名,防止覆盖
        String fileName = UUID.randomUUID().toString() + "." + contentType;
        // 创建一个目录对象
        File dir = new File(basePath);
        // 判断目录是否存在,不存在则创建
        if(!dir.exists()){
            dir.mkdirs();
        }
        // 获取文件的md5,判断磁盘是否存在相同的文件
        // 就算文件的md5相同 也要存到数据库并展示给前台
        String md5 = SecureUtil.md5(file.getInputStream());
        SysFiles dbFiles = getFileByMd5(md5);
        if (dbFiles != null) {
            // 文件已存在
            url = dbFiles.getUrl();
        } else {
            // 上传文件到磁盘
            file.transferTo(new File(basePath+fileName));
//            url = "http://localhost:"+serverPort+"/files/" + fileName;
            url = "http://"+serverIP+":"+serverPort+"/files/" + fileName;
        }
        // 保存到数据库
        SysFiles dbFile = new SysFiles();
        dbFile.setCreateTime(DateUtil.toLocalDateTime(new Date()));
        dbFile.setName(originalFilename);
        dbFile.setType(contentType);
        dbFile.setSize(size/1024);
        dbFile.setUrl(url);
        dbFile.setMd5(md5);
        fileMapper.insert(dbFile);
        return url;
    }
    /**
     * 通过文件的md5查询文件
     * 同一个文件不会在磁盘中存在多个
     * @param md5
     * @return
     */
    private SysFiles getFileByMd5(String md5) {
        // 查询文件的md5是否存在
        LambdaQueryWrapper<SysFiles> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysFiles::getMd5, md5);
        queryWrapper.eq(SysFiles::getIsDelete,0);
        List<SysFiles> filesList = fileMapper.selectList(queryWrapper);
        return filesList.size() == 0 ? null : filesList.get(0);
    }

    public void download(String basePath, String url, HttpServletResponse response) throws IOException {
        // 根据文件的唯一标识码获取文件
        File uploadFile = new File(basePath + url);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(url, "UTF-8"));
        response.setContentType("application/octet-stream");
        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    public IPage<SysFiles> findPageOfFiles(SysFilesDTO sysFilesDTO) {
        LambdaQueryWrapper<SysFiles> lqw = new LambdaQueryWrapper<>();
        lqw.orderByDesc(SysFiles::getCreateTime);
        lqw.like(Strings.isNotEmpty(sysFilesDTO.getName()),SysFiles::getName,sysFilesDTO.getName());
        lqw.like(Strings.isNotEmpty(sysFilesDTO.getType()),SysFiles::getType,sysFilesDTO.getType());
        Page<SysFiles> iPage = new Page<>(sysFilesDTO.getPage(), sysFilesDTO.getLimit());
        return page(iPage,lqw);
    }
}